package com.tanhua.server.service;

import com.tanhua.commons.exception.TanHuaException;
import com.tanhua.commons.templates.OssTemplate;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.Comment;
import com.tanhua.domain.mongo.Publish;
import com.tanhua.domain.mongo.Visitor;
import com.tanhua.domain.vo.MomentVo;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.PublishVo;
import com.tanhua.domain.vo.VisitorVo;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.mongo.PublishApi;
import com.tanhua.dubbo.api.mongo.VisitorApi;
import com.tanhua.server.interceptors.UserHolder;
import com.tanhua.server.utils.RelativeDateFormat;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class MomentService {

    @Reference
    private PublishApi publishApi;

    @Reference
    private UserInfoApi userInfoApi;

    @Reference
    private VisitorApi visitorApi;

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 发布动态
     * @param vo
     * @param imageContent
     */
    public void postMoment(PublishVo vo, MultipartFile[] imageContent) {
        //1. 把图片上传到oss上，得到图片的url
        List<String> medias = new ArrayList<>();
        if(null != imageContent){
            try {
                for (MultipartFile pic : imageContent) {
                    medias.add(ossTemplate.upload(pic.getOriginalFilename(), pic.getInputStream()));
                }
            } catch (IOException e) {
                log.error("上传图片失败!",e);
                throw new TanHuaException("上传图片失败!");
            }
        }
        //2. 构建动态的pojo
        Publish pojo = new Publish();
        //3. 把vo数据复制到pojo里
        BeanUtils.copyProperties(vo,pojo);
        //4. 设置动态的作者id=登录用户id
        pojo.setUserId(UserHolder.getUserId()); // 作者
        pojo.setMedias(medias); // 动态的所有图片
        pojo.setLocationName(vo.getLocation());
        pojo.setSeeType(1);//1-公开
        pojo.setState(0);// state=0: 未审核
        //5. 调用api发布动态
        publishApi.add(pojo);
    }

    /**
     * 分页查询好友动态
     * @param page
     * @param pageSize
     * @return
     */
    public PageResult<MomentVo> queryFriendPublishList(Long page, Long pageSize) {
        //1. 获取登录用户id
        Long loginUserId = UserHolder.getUserId();
        //2. 通过登录用户id 分页查询好友动态得到的是pageResult
        PageResult pageResult = publishApi.queryFriendPublishList(loginUserId, page, pageSize);
        //3. 获取分页结果集
        List<Publish> publishList = pageResult.getItems();
        //4. 非空判断
        List<MomentVo> voList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(publishList)) {
            //5. 有值,补充用户详情
            //5.1 遍历动态列表，
            List<Long> userIds = publishList.stream().map(Publish::getUserId).collect(Collectors.toList());
            //5.2 获取作者的id, 调用api查询作者信息
            List<UserInfo> userInfoList = userInfoApi.findByBatchId(userIds);
            // 转成map key=用户id, value=用户信息对象
            Map<Long, UserInfo> userInfoMap = userInfoList.stream().collect(Collectors.toMap(UserInfo::getId, u -> u));
            //6. 转成vo
            for (Publish publish : publishList) {
                MomentVo vo = new MomentVo();
                // 获取作者id
                Long authorId = publish.getUserId();
                // 获取作者信息
                UserInfo userInfo = userInfoMap.get(authorId);
                BeanUtils.copyProperties(userInfo, vo);
                vo.setUserId(authorId);
                vo.setTags(StringUtils.split(userInfo.getTags(), ","));

                // 复制动态信息
                BeanUtils.copyProperties(publish, vo);
                vo.setId(publish.getId().toHexString());
                vo.setImageContent(publish.getMedias().toArray(new String[0]));

                vo.setDistance("500米");
                vo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));

                // 判断 当前登录用户是否对这个动态点过赞, 如果redis中的key存在就代表 点赞过了
                String key = "publish_like_" + UserHolder.getUserId() + "_" + vo.getId();
                if (stringRedisTemplate.hasKey(key)) {
                    // 有这个key, 点赞过了
                    vo.setHasLiked(1);
                }

                // 判断 当前登录用户是否对这个动态点喜欢, 如果redis中的key存在就代表 喜欢过了
                key = "publish_love_" + UserHolder.getUserId() + "_" + vo.getId();
                if (stringRedisTemplate.hasKey(key)) {
                    // 有这个key, 喜欢过了
                    vo.setHasLoved(1);
                }
                voList.add(vo);

            }
        }
        //7. voList设置到 pageResult
        pageResult.setItems(voList);
        //8. 返回pageResult
        return pageResult;
    }

    /**
     * 查询推荐动态
     * @param page
     * @param pageSize
     * @return
     */
    public PageResult<MomentVo> queryRecommendPublishList(Long page, Long pageSize) {
        //1. 获取登录用户id
        Long loginUserId = UserHolder.getUserId();
        //2. 通过登录用户id 分页查询推荐动态得到的是pageResult
        PageResult pageResult = publishApi.queryRecommendPublishList(loginUserId, page, pageSize);
        //3. 获取分页结果集
        List<Publish> publishList = pageResult.getItems();
        //4. 非空判断
        List<MomentVo> voList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(publishList)) {
            //5. 有值,补充用户详情
            //5.1 遍历动态列表，
            List<Long> userIds = publishList.stream().map(Publish::getUserId).collect(Collectors.toList());
            //5.2 获取作者的id, 调用api查询作者信息
            List<UserInfo> userInfoList = userInfoApi.findByBatchId(userIds);
            // 转成map key=用户id, value=用户信息对象
            Map<Long, UserInfo> userInfoMap = userInfoList.stream().collect(Collectors.toMap(UserInfo::getId, u -> u));
            //6. 转成vo
            for (Publish publish : publishList) {
                MomentVo vo = new MomentVo();
                // 获取作者id
                Long authorId = publish.getUserId();
                // 获取作者信息
                UserInfo userInfo = userInfoMap.get(authorId);
                BeanUtils.copyProperties(userInfo, vo);
                vo.setUserId(authorId);
                vo.setTags(StringUtils.split(userInfo.getTags(), ","));

                // 复制动态信息
                BeanUtils.copyProperties(publish, vo);
                vo.setId(publish.getId().toHexString());
                vo.setImageContent(publish.getMedias().toArray(new String[0]));

                vo.setDistance("500米");
                vo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));

                // 判断 当前登录用户是否对这个动态点过赞, 如果redis中的key存在就代表 点赞过了
                String key = "publish_like_" + UserHolder.getUserId() + "_" + vo.getId();
                if (stringRedisTemplate.hasKey(key)) {
                    // 有这个key, 点赞过了
                    vo.setHasLiked(1);
                }

                // 判断 当前登录用户是否对这个动态点喜欢, 如果redis中的key存在就代表 喜欢过了
                key = "publish_love_" + UserHolder.getUserId() + "_" + vo.getId();
                if (stringRedisTemplate.hasKey(key)) {
                    // 有这个key, 喜欢过了
                    vo.setHasLoved(1);
                }
                voList.add(vo);
            }
        }
        //7. voList设置到 pageResult
        pageResult.setItems(voList);
        //8. 返回pageResult
        return pageResult;
    }

    /**
     * 分页查询我的动态, 查看某个用户的动态
     * @param userId
     * @param page
     * @param pageSize
     * @return
     */
    public PageResult<MomentVo> queryMyPublishList(Long userId, Long page, Long pageSize) {
        //1. 获取登录用户id
        Long searchUserId = UserHolder.getUserId();
        if(null != userId){
            searchUserId = userId;
        }
        //2. 通过登录用户id 分页查询好友动态得到的是pageResult
        PageResult pageResult = publishApi.queryUserPublishList(searchUserId, page, pageSize);
        //3. 获取分页结果集
        List<Publish> publishList = pageResult.getItems();
        //4. 非空判断
        List<MomentVo> voList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(publishList)) {
            //5. 有值,补充用户详情
            UserInfo userInfo = userInfoApi.findById(searchUserId);
            //6. 转成vo
            for (Publish publish : publishList) {
                MomentVo vo = new MomentVo();
                // 获取作者id
                Long authorId = publish.getUserId();
                BeanUtils.copyProperties(userInfo, vo);
                vo.setUserId(authorId);
                vo.setTags(StringUtils.split(userInfo.getTags(), ","));

                // 复制动态信息
                BeanUtils.copyProperties(publish, vo);
                vo.setId(publish.getId().toHexString());
                vo.setImageContent(publish.getMedias().toArray(new String[0]));

                vo.setDistance("500米");
                vo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));
                // 判断 当前登录用户是否对这个动态点过赞, 如果redis中的key存在就代表 点赞过了
                String key = "publish_like_" + UserHolder.getUserId() + "_" + vo.getId();
                if (stringRedisTemplate.hasKey(key)) {
                    // 有这个key, 点赞过了
                    vo.setHasLiked(1);
                }
                voList.add(vo);
            }
        }
        //7. voList设置到 pageResult
        pageResult.setItems(voList);
        //8. 返回pageResult
        return pageResult;
    }


    /**
     * 单条动态信息
     * @param publishId
     * @return
     */
    public MomentVo findById(String publishId) {
        //1. 调用动态的api,通过id查询动态详情
        Publish publish = publishApi.findById(publishId);
        //2. 转成vo
        //2.1 查询作者的信息
        UserInfo userInfo = userInfoApi.findById(publish.getUserId());
        //2.2 转vo
        MomentVo vo = new MomentVo();
        // 获取作者id
        BeanUtils.copyProperties(userInfo, vo);
        vo.setUserId(publish.getUserId());
        vo.setTags(StringUtils.split(userInfo.getTags(), ","));

        // 复制动态信息
        BeanUtils.copyProperties(publish, vo);
        vo.setId(publish.getId().toHexString());
        vo.setImageContent(publish.getMedias().toArray(new String[0]));

        vo.setDistance("500米");
        vo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));
        //3. 返回
        return vo;
    }

    /**
     * 首页中的 最近的访客
     * @return
     */
    public List<VisitorVo> query4Visitors() {
        //1. 通过登录用户id查询最近的4个访客
        List<Visitor> visitorList = visitorApi.findLast4Visitors(UserHolder.getUserId());
        //2. 获取所有访客id
        List<VisitorVo> voList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(visitorList)) {
            List<Long> userIds = visitorList.stream().map(Visitor::getVisitorUserId).collect(Collectors.toList());
            //3. 批量查询访客信息
            List<UserInfo> userInfoList = userInfoApi.findByBatchId(userIds);
            //4. 转成map
            Map<Long, UserInfo> userInfoMap = userInfoList.stream().collect(Collectors.toMap(UserInfo::getId, u -> u));
            //5. 遍历访客列表转成vo
            for (Visitor visitor : visitorList) {
                VisitorVo vo = new VisitorVo();
                // 获取访客信息
                UserInfo userInfo = userInfoMap.get(visitor.getVisitorUserId());
                BeanUtils.copyProperties(userInfo, vo);
                vo.setTags(StringUtils.split(userInfo.getTags(), ","));
                // 缘分值
                vo.setFateValue(visitor.getScore().intValue());
                voList.add(vo);
            }
        }
        //6. 返回
        return voList;
    }
}
